#include "graphs_RenderingDefs.h"

void graphs::save_pixel (const int &bpp,
						 const uint32_t &src,
						 uint8_t *dest)
{
		switch(bpp) 
		{
			case 1:
				*dest = src;
				break;

			case 2:
				*(Uint16 *)dest = src;
				break;

			case 3:
				if(SDL_BYTEORDER == SDL_BIG_ENDIAN) 
				{
					dest[0] = (src >> 16) & 0xff;
					dest[1] = (src >> 8) & 0xff;
					dest[2] = src & 0xff;
				} 
				else 
				{
					dest[0] = src & 0xff;
					dest[1] = (src >> 8) & 0xff;
					dest[2] = (src >> 16) & 0xff;
				}
				break;

			case 4:
				*(uint32_t *)dest = src;
				break;

			default:
				throw RenderingException("Invalid bytes-per-pixel value.");
				break;
		}
}

uint32_t graphs::getpixel (SDL_Surface *surface, 
						   int x, 
						   int y)
{
	int bpp = surface->format->BytesPerPixel;
	/* Here p is the address to the pixel we want to retrieve */
	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

	switch(bpp) 
	{
		case 1:
			return *p;

		case 2:
			return *(Uint16 *)p;

		case 3:
			if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
				return p[0] << 16 | p[1] << 8 | p[2];
			else
				return p[0] | p[1] << 8 | p[2] << 16;

		case 4:
			return *(uint32_t *)p;

		default:
			return 0;       /* shouldn't happen, but avoids warnings */
	}
}

void graphs::putpixel (SDL_Surface *surface, 
					   int x, 
					   int y, 
					   uint32_t pixel)
{
	int bpp = surface->format->BytesPerPixel;
	/* Here p is the address to the pixel we want to set */
	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

	try
	{
		save_pixel(bpp, pixel, p);
	}
	catch(RenderingException ex)
	{
		throw RenderingException(strcat("Unable to store pixel data: ", ex.what()));
	}
}